/*
---
name: MPG.GalleryController

description:

license: MIT-style

authors:
- Noritaka Horio

requires:
  - Core/Core
  - Core/Type
  - Core/Element
  - Core/Element.Event
  - Core/Element.Style
  - Core/Element.Dimensions
  - Core/Class
  - Core/Class.Extra
  - More/Fx.Elements
  - Interface/Interface
  - MPG/MPG.IGallery
  - MPG/MPG.Spinner

provides: [MPG.GalleryController]

...
*/
(function($){

	var MPG = this.MPG = (this.MPG || {});

	MPG.GalleryController = new Class({

		Interface: MPG.IGallery,

		Implements: [Options, Events],

		options: {
			current: 0,
			elements: [],
			duration: 400,
			imageClass: 'photography',
			transition: 'expo:out',
			progressMessage: 'It optimizes it for the device.',
			actions: {
				defaultAction: '/',
				landscapeAction: '/landscape',
				portraitAction: '/portrait'
			}
/*
			onChangeStart
			onChangeEnd
			onPrev
			onNext
			onFirst
			onLast
*/
		},

		_current: 0,
		_elements: [],

		initialize: function(gallery, options){
			this.setOptions(options);
			this.container = (Type.isString(gallery)) ? $(gallery) : gallery;
			this._setup();
		},

		_setup: function(){
			var ops = this.options;
			var imageClass = ops.imageClass;
			var container = this.container;
			var elements = container.getElements('.' + imageClass);
			this.setCurrent(ops.current);
			this.setElements(elements);
			this._setupLoader();
		},

		_setupEffect: function(){
			var self = this;
			var elements = this.getElements();
			var options = this.options;
			var fxOptions = {
				duration: options.duration,
				transition: options.transition,
				onStart: this._onStart.bind(self),
				onComplete: this._onComplete.bind(self)
			};
			this._fx = new Fx.Elements(elements, fxOptions);
		},

		_setupElements: function(){
			var left = 0;
			var elements = this.getElements();
			elements.each(function(element, key){
				var width =  element.getWidth();
				var styles = {
					'position': 'absolute',
					'left': left
				};
				element.setStyles(styles);
				element.store('base', left);
				left = left + width;
			});
			this.container.setStyle('height', elements.getMaxHeight());
		},

		_setupLoader: function(){
			var self = this;
			this.spinner = new MPG.Spinner();
			this.spinner.setMessage(this.options.progressMessage);
			this.container.set('load', {
				onSuccess: this._onSuccess.bind(self)
			});
		},

		getCurrent: function(){
			return this._current;
		},

		setCurrent: function(current){
			this._current = current;
		},

		getTotal: function(){
			var elements = this.getElements();
			return elements.length;
		},

		getElement: function(index){
			return this._elements[index];
		},

		getElements: function(){
			return this._elements;
		},

		setElements: function(elements){
			if (!Type.isArray(elements) && elements.length <= 0){
				return;
			}
			this._elements = elements;
			this._setupEffect();
			this._setupElements();
			this._set(this.getCurrent());
		},

		_set: function(index){
			if (this.getTotal() <= 0){
				return;
			}
			this.setCurrent(index);
			this._animate();
		},

		_onStart: function(){
			var index = this.getCurrent();
			var element = this.getElement(index);
			this.fireEvent('changeStart', [index, element]);
	    },

		_onComplete: function(){
			var index = this.getCurrent();
			var element = this.getElement(index);
			this.fireEvent('changeEnd', [index, element]);
	    },

		_onSuccess: function(tree, elements, html, javascript){
	    	var photoSelecter = '.' + this.options.imageClass;
			var elements = this.container.getElements(photoSelecter);
			this.setElements(elements);
			this.spinner.hide();
			this.fireEvent('load', [html]);
		},

		defaultAction: function(){
			var actions = this.options.actions;
			this.spinner.show();
			this.container.load(actions.defaultAction);
		},

		landscapeAction: function(){
			var actions = this.options.actions;
			this.spinner.show();
			this.container.load(actions.landscapeAction);
	    },

		portraitAction: function(){
			var actions = this.options.actions;
			this.spinner.show();
			this.container.load(actions.portraitAction);
	    },

	    _animate: function(){
			var offsets = {};
			var index = this.getCurrent();
			var sp = this.getElement(index);
			var spp = sp.retrieve('base');
			var elements = this.getElements();
			elements.each(function(element, key){
				var app = element.retrieve('base');
				var sl = element.getPosition().x;
				var el = (spp > app) ? -(spp - app) : (app - spp);
				offsets[key] = {
					left: [sl, el],
					opacity: (index == key) ? [0, 1] : [1, 0]
				};
			});
			this._fx.start(offsets);
	    },

		prev: function(){
			var prevIndex = this._current - 1;
			if (this.validate(prevIndex)) {
				var element = this.getElement(prevIndex);
				this._set(prevIndex);
				this.fireEvent('prev', [prevIndex, element]);
			}
		},

		next: function(){
			var nextIndex = this._current + 1;
			if (this.validate(nextIndex)) {
				var element = this.getElement(nextIndex);
				this._set(nextIndex);
				this.fireEvent('next', [nextIndex, element]);
			}
		},

		first: function(){
			var first = 0;
			var element = this.getElement(first);
			this._set(first);
			this.fireEvent('first', [first, element]);
		},

		last: function(){
			var total = this._elements.length - 1;
			var element = this.getElement(total);
			this._set(total);
			this.fireEvent('last', [total, element]);
		},

		validate: function(index){
			var total = this._elements.length;
			return (index >= 0 && total > index);
		},

		isValid: function(){
			var current = this.getCurrent();
			return this.validate(current);
		}

	});

}(document.id));
